﻿using Castle.DynamicProxy;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using Marmat.Common.Http.Attributes;
using System.Linq;
using System.Net;

namespace Marmat.Common.Http
{
    internal class HttpMethodAddressInterceptor
    {


        public Uri BuildUri(ApiActionContext context)
        {
            Uri host = context.HttpApiConfig.HttpHost;

            #region 获取请求地址的主路径
            MethodInfo method = context.ActionDescriptor.Method;
            HttpGet httpGet = method.GetCustomAttribute<HttpGet>();
            HttpPost httpPost = method.GetCustomAttribute<HttpPost>();
            HttpHost classHost = context.ActionDescriptor.DeclaringType.GetCustomAttribute<HttpHost>();
            var parameters = method.GetParameters();

            // 如果首个参数是string类型，并且标注了 UriAttribute 特性的话，则将该参数作为请求的地址。
            if (parameters.Length > 0 && parameters[0].ParameterType == typeof(string) && parameters[0].CustomAttributes.FirstOrDefault(x => x.AttributeType == typeof(UriAttribute)) is not null)
            {
                host = new Uri(context.ActionDescriptor.Arguments[0].ToString());
                context.ActionDescriptor.ignoreArgumentCollection.Add(parameters[0].Name);
            }
            else if (classHost is not null && !string.IsNullOrEmpty(classHost.Host))
                host = new Uri(host, classHost.Host + (classHost.Host.EndsWith("/") ? "" : "/"));
            if (httpGet is not null)
                host = new Uri(host, httpGet.Template ?? method.Name);
            else if (httpPost is not null)
                host = new Uri(host, httpPost.Template ?? method.Name);
            else
                host = new Uri(host, method.Name);
            #endregion

            #region 获取请求地址的参数信息
            if (parameters.Length > 0)
            {
                bool first = true;
                StringBuilder builder = new();
                for (int index = 0; index < parameters.Length; index++)
                {
                    var parameter = parameters[index];

                    // 如果作为FromBody、FromForm、Uri特性，则排除。
                    if (parameter.CustomAttributes.FirstOrDefault(x => x.AttributeType == typeof(FromBodyAttribute) || x.AttributeType == typeof(FormContentAttribute) || x.AttributeType == typeof(FromFormAttribute) || x.AttributeType == typeof(UriAttribute)) is not null)
                        continue;

                    var name = parameter.Name;
                    var value = context.ActionDescriptor.Arguments[index];
                    string valueString;

                    if (parameter.GetCustomAttribute<AliasAsAttribute>() is AliasAsAttribute alias)
                        name = alias.AliasName;

                    if (parameter.CustomAttributes.FirstOrDefault(x => x.AttributeType == typeof(JsonContentAttribute)) is not null)
                        valueString = Newtonsoft.Json.JsonConvert.SerializeObject(value, Newtonsoft.Json.Formatting.None);
                    else
                        valueString = value?.ToString();

                    // 如果请求地址包含变量时，通过更换关键字来地址的更新。
                    if (host.OriginalString.Contains("{" + name + "}"))
                    {
                        host = new Uri(host.OriginalString.Replace("{" + name + "}", valueString));
                        context.ActionDescriptor.ignoreArgumentCollection.Add(parameter.Name);
                        continue;
                    }

                    builder.Append(first ? "?" : "&");
                    first = false;
                    //builder.Append($"{name}={valueString}");
                    builder.Append($"{WebUtility.UrlEncode(name)}={WebUtility.UrlEncode(valueString)}");
                }
                if (builder.Length > 0)
                    host = new Uri(host, builder.ToString());
            }
            #endregion

            return host;
        }
    }
}
